package com.fitz.task;

import com.alibaba.druid.support.json.JSONUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 描    述：批量处理数据
 * 创 建 者：gousili
 * 修 改 者：
 * 创建时间：2019-09-20 9:37
 */
@Slf4j
@Service
public class BatchExecutorData<T> {

    private LinkedBlockingQueue<T> dataQueue = new LinkedBlockingQueue<>();

    ExecutorService executor = new ThreadPoolExecutor(4, 8, 60, TimeUnit.MICROSECONDS,
            new LinkedBlockingQueue<>(1024),new ThreadPoolExecutor.CallerRunsPolicy());

    private List<T> list = new ArrayList<>();

    public void putData(T t){
        try {
            dataQueue.put(t);
        } catch (InterruptedException e) {
            log.error("batch execute data error");
            e.printStackTrace();
        }
    }

    public void addList(List<T> dataList){
        for (T t : dataList){
            try {
                dataQueue.put(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @PostConstruct
    public void init(){
        executor.submit(() ->{
            while (true){
                T t = null;
                boolean pollTimeOut = false;
                try {
                    t = dataQueue.poll(1,TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    log.error("batch execute error");
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
                if (null != t){
                    list.add(t);
                }else {
                    pollTimeOut = true;
                }
                //超时时间1 秒，每秒不足20也会执行
                if (list.size() == 20 || (pollTimeOut && !CollectionUtils.isEmpty(list))){
                    log.info("batch execute num : [{}]",list.size());
                    StringBuilder sb = new StringBuilder();
                    for (T t1 : list){
                        sb.append(JSONUtils.toJSONString(t1));
                    }
                    sb.append("****\n");
                    System.out.println(sb.toString());
                    log.info("batch execute end : [{}]",list.size());
//                    messageService.batchInsert((List<PushNoticeLog>) list);
                    list.clear();
                }
            }
        });
    }
}
